package net.droiding.server.fetch;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.droiding.server.dao.Dao;
import net.droiding.server.parser.KmlParser;
import net.droiding.server.parser.KmlParserFactory;
import net.droiding.server.pojo.Provider;
import net.droiding.server.pojo.ProviderKey;
import net.droiding.server.pojo.ProviderType;
import net.droiding.server.pojo.Station;
import net.droiding.server.pojo.StationData;

public class BcnFetchServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 874765340158714117L;
	
	private static final String BCN_URL = "http://www.bicing.com/localizaciones/localizaciones.php";
	
	
	private KmlParser parser = KmlParserFactory.newParser(ProviderKey.BCN);
	
	private Provider provider = null;
	
	private Dao dao = new Dao();
	
	@Override
	public void init() throws ServletException {
		try {
			loadProvider();
		} catch (Throwable t) {
			throw new ServletException(t);
		}
	}

	private void loadProvider() throws Exception {
		provider = dao.getProviderByKey(ProviderKey.BCN);
		if (provider == null) {
			provider = new Provider();
			provider.setKey(ProviderKey.BCN);
			provider.setLocation("Barcelona, Espa\u00F1a");
			provider.setName("Bicing");
			provider.setWebsite("http://www.bicing.com/");
			provider.setType(ProviderType.clearchannel);
			provider.setZoomLevel(13);
			provider.setLatitude(Double.parseDouble("41.39805"));
			provider.setLongitude(Double.parseDouble("2.18008"));
			provider.setLastUpdate(System.currentTimeMillis());
			provider = dao.insertProvider(provider);
		}
	}	
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		try {
			byte[] pageBytes = retrievePage();
			String page = new String(pageBytes, "ISO-8859-1");
			String kml = processPage(page);
			List<Station> stations = parser.parse(kml.getBytes("UTF-8"));
			int found = stations.size();
			int newStations = 0;
			int updatedStations = 0;
			long lastUpdate = System.currentTimeMillis();
			for (Station s : stations) {
				s.setLastUpdate(lastUpdate);
				Station stationDB = dao.getStationByKey(s.getProviderKey(), s.getKey());
				//new station found !!
				if (stationDB == null) {
					newStations++;	
					try {
						dao.beginTransaction();
						provider.setLastUpdate(lastUpdate);
						provider = dao.updateProvider(provider);
						dao.insertStation(s);
						if (s.getData().size() == 1) {
							s.getData().get(0).setLastUpdate(lastUpdate);
							dao.insertStationData(s.getData().get(0));
						}
						dao.commit();
					} catch (Exception e) {
						dao.rollback();
						//log exception
					}
					continue;
				} 
				if (s.getData().size() == 1)  {
					StationData newData = s.getData().get(0);
					newData.setLastUpdate(lastUpdate);
					
					try {
						dao.beginTransaction();
						dao.insertStationData(newData);
						if (stationDB.getData().size() > 0) {
							StationData dbData = stationDB.getData().get(0);
							if (newData.getBikes() != dbData.getBikes() || newData.getSlots() != dbData.getSlots() || 
									newData.isAvailable() != dbData.isAvailable()) {
								updatedStations++;
								dao.updateStation(s);
							}
						}
						dao.commit();
					} catch (Exception e) {
						dao.rollback();
						//log exception
					}
					continue;
				}
			}
			PrintWriter pw = resp.getWriter();
			pw.println("<html><body><h1>");
			pw.println(ProviderKey.BCN.getValue() + ": found=" + found + " new=" + newStations + " upd=" + updatedStations);
			pw.println("</h1></body></html>");
			pw.close();
		} catch (Throwable t) {
			throw new ServletException(t);
		}
	}

	private byte[] retrievePage() throws Exception {
		URL u = new URL(BCN_URL);
		URLConnection conn = u.openConnection();
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		InputStream is = conn.getInputStream();
		byte[] buf = new byte[1024];
		int count = 0;
		while (((count = is.read(buf, 0, 1024)) > 0)) {
			bos.write(buf, 0, count);
		}
		return bos.toByteArray();
	}

	
	private String processPage(String page) {
		int start = page.indexOf("<kml xmlns=\"http://earth.google.es/kml/2.0\">");
		int end = page.indexOf("</kml>");
		end += 6;
		String kml = page.substring(start, end);
		return kml;
	}
}
